package com.cardone.platform.authority.service;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.Setter;

import org.apache.commons.lang3.ArrayUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;

import com.cardone.common.dto.PaginationDto;
import com.cardone.common.utils.EntityUtils;
import com.cardone.persistent.CommonDtoAttributes;
import com.cardone.platform.authority.dao.NavigationDao;
import com.cardone.platform.authority.dto.NavigationDto;

/**
 * 导航服务
 * 
 * @author yaoht
 * 
 */
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class NavigationDefaultService implements NavigationService {
	/**
	 * 导航数据持久
	 */
	private NavigationDao navigationDao;

	@Override
	@Transactional
	@CacheEvict(value = NavigationService.BEAN_ID, allEntries = true)
	public int deleteNavigationByCode(@NonNull NavigationDto deleteNavigation) {
		return this.navigationDao.deleteByCode(deleteNavigation, new String[] {});
	}

	@Override
	@Transactional
	@CacheEvict(value = NavigationService.BEAN_ID, allEntries = true)
	public int deleteNavigationByIds(@NonNull NavigationDto deleteNavigation) {
		return this.navigationDao.deleteByIds(deleteNavigation);
	}

	@Override
	@Cacheable(value = NavigationService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public List<NavigationDto> findListNavigationByCode(@NonNull NavigationDto findListNavigation) {
		return this.navigationDao.findListByCode(NavigationDto.class, findListNavigation, new String[] {}, new String[] {});
	}

	@Override
	@Cacheable(value = NavigationService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public List<NavigationDto> findListNavigationByName(@NonNull NavigationDto findListNavigation) {
		return this.navigationDao.findListByName(NavigationDto.class, findListNavigation);
	}

	@Override
	@Cacheable(value = NavigationService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public NavigationDto findNavigationByCode(@NonNull NavigationDto findNavigation) {
		return this.navigationDao.findByCode(NavigationDto.class, findNavigation, null, CommonDtoAttributes.id.name());
	}

	@Override
	@Cacheable(value = NavigationService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public NavigationDto findNavigationById(@NonNull NavigationDto findNavigation) {
		return this.navigationDao.findByCode(NavigationDto.class, findNavigation, null, CommonDtoAttributes.id.name());
	}

	@Override
	@Cacheable(value = NavigationService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public PaginationDto<NavigationDto> paginationNavigationByCode(@NonNull NavigationDto paginationNavigation) {
		return this.navigationDao.paginationByCode(NavigationDto.class, paginationNavigation);
	}

	@Override
	@Cacheable(value = NavigationService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public PaginationDto<Map<String, Object>> paginationNavigationByName(@NonNull NavigationDto paginationNavigation) {
		return this.navigationDao.paginationByName(paginationNavigation);
	}

	@Override
	@Cacheable(value = NavigationService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public Integer readNavigationByCodeNqId(@NonNull NavigationDto readNavigation) {
		return this.navigationDao.readByCodeNqId(Integer.class, readNavigation);
	}

	@Override
	@Cacheable(value = NavigationService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public Integer readNavigationByName(@NonNull NavigationDto readNavigation) {
		return this.navigationDao.readByName(Integer.class, null, readNavigation);
	}

	@Override
	@CacheEvict(value = NavigationService.BEAN_ID, allEntries = true)
	public void reload() {
		this.navigationDao.reload();
	}

	@Override
	@Transactional
	@CacheEvict(value = NavigationService.BEAN_ID, allEntries = true)
	public NavigationDto saveNavigationByIdOrCode(@NonNull NavigationDto saveNavigation) {
		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(saveNavigation, CommonDtoAttributes.code.name());

		final NavigationDto oldNavigation = this.navigationDao.findByCode(NavigationDto.class, saveNavigation, null,
		        whereAndEqProperties);

		if (oldNavigation == null) {
			saveNavigation.setId(UUID.randomUUID().toString());

			this.navigationDao.insertByCode(saveNavigation);

			final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(saveNavigation);

			return this.navigationDao.findByCode(NavigationDto.class, saveNavigation, null, notNullIdProperties);
		}

		final String[] useProperties = EntityUtils.addNotNullTimeSegmentProperties(new String[] { CommonDtoAttributes.parentId.name(),
		        CommonDtoAttributes.typeId.name(), CommonDtoAttributes.code.name(), CommonDtoAttributes.name.name(),
		        CommonDtoAttributes.orderCode.name(), CommonDtoAttributes.value.name(), CommonDtoAttributes.remark.name() },
		        saveNavigation);

		final String[] updateProperties = com.cardone.common.utils.BeanUtils.diffProperties(saveNavigation, oldNavigation,
		        useProperties);

		if (ArrayUtils.isEmpty(updateProperties)) {
			return oldNavigation;
		}

		final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(oldNavigation);

		com.cardone.common.utils.BeanUtils.copyProperties(oldNavigation, saveNavigation, notNullIdProperties);

		this.navigationDao.updateByCode(saveNavigation, updateProperties, notNullIdProperties);

		return this.navigationDao.findByCode(NavigationDto.class, oldNavigation, null, notNullIdProperties);
	}

	@Override
	@Transactional
	@CacheEvict(value = NavigationService.BEAN_ID, allEntries = true)
	public NavigationDto saveNavigationByName(@NonNull NavigationDto saveNavigation) {
		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(saveNavigation, CommonDtoAttributes.code.name());

		final NavigationDto oldNavigation = this.navigationDao.findByCode(NavigationDto.class, saveNavigation, null,
		        whereAndEqProperties);

		if (oldNavigation == null) {
			saveNavigation.setId(UUID.randomUUID().toString());

			this.navigationDao.insertByCode(saveNavigation);

			final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(saveNavigation);

			return this.navigationDao.findByCode(NavigationDto.class, saveNavigation, null, notNullIdProperties);
		}

		final String[] useProperties = EntityUtils.addNotNullTimeSegmentProperties(new String[] { CommonDtoAttributes.parentId.name(),
		        CommonDtoAttributes.typeId.name(), CommonDtoAttributes.code.name(), CommonDtoAttributes.name.name(),
		        CommonDtoAttributes.orderCode.name(), CommonDtoAttributes.value.name(), CommonDtoAttributes.remark.name() },
		        saveNavigation);

		final String[] updateProperties = com.cardone.common.utils.BeanUtils.diffProperties(saveNavigation, oldNavigation,
		        useProperties);

		if (ArrayUtils.isEmpty(updateProperties)) {
			return oldNavigation;
		}

		final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(oldNavigation);

		com.cardone.common.utils.BeanUtils.copyProperties(oldNavigation, saveNavigation, notNullIdProperties);

		this.navigationDao.updateByCode(saveNavigation, updateProperties, notNullIdProperties);

		return this.navigationDao.findByCode(NavigationDto.class, oldNavigation, null, notNullIdProperties);
	}

	@Override
	@Transactional
	@CacheEvict(value = NavigationService.BEAN_ID, allEntries = true)
	public int updateNavigationByCode(@NonNull NavigationDto updateNavigation) {
		return this.navigationDao.updateByCode(updateNavigation, new String[] {}, new String[] {});
	}

	@Override
	@Transactional
	@CacheEvict(value = NavigationService.BEAN_ID, allEntries = true)
	public int updateNavigationByIds(@NonNull NavigationDto updateNavigation) {
		return this.navigationDao.updateByIds(updateNavigation);
	}
}